commonlibsse_ng\re\h/hkArray.rs
1//! # hkArray
2//!
3//! This module defines the `hkArray` struct, a dynamic array-like structure that
4//! mimics the behavior of a C++ container with methods for array manipulation,
5//! including dynamic resizing, accessors, and iterators.
6mod array_base;
7
8use core::ops::{Index, IndexMut};
9
10pub use self::array_base::{
11 hkArrayBase, hkArrayDrain, hkArrayIterMut, hkArrayIterator, hkArrayRefIterator,
12};
13use crate::re::MemoryManager::TESGlobalAlloc;
14use std_fork::alloc::SelflessAllocator;
15
16/// A dynamic array container C++'s `hkArray`, backed by a custom allocator.
17///
18/// # Example
19/// ```
20/// use commonlibsse_ng::re::hkArray::hkArray;
21///
22/// let mut array = hkArray::<i32>::new();
23/// array.push(1);
24/// array.push(2);
25/// assert_eq!(array.len(), 2);
26/// assert_eq!(array[0], 1);
27/// ```
28///
29/// Note: The default allocator (`SkyrimAllocator`) only works in-game.
30/// For examples outside of the game, use `RustAllocator`.
31#[repr(C)]
32#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
33pub struct hkArray<T, A: SelflessAllocator = TESGlobalAlloc> {
34 __base: hkArrayBase<T, A>,
35}
36
37impl<T, A> hkArray<T, A>
38where
39 A: SelflessAllocator,
40{
41 /// Creates a new empty array.
42 ///
43 /// # Example
44 /// ```
45 /// use commonlibsse_ng::re::hkArray::hkArray;
46 ///
47 /// let array: hkArray<u32> = hkArray::new();
48 /// assert!(array.is_empty());
49 /// ```
50 #[inline]
51 pub const fn new() -> Self {
52 Self { __base: hkArrayBase::new() }
53 }
54
55 #[inline]
56 pub fn with_capacity(capacity: i32) -> Self {
57 Self { __base: hkArrayBase::with_capacity(capacity) }
58 }
59
60 /// Returns the number of elements in the array.
61 ///
62 /// # Example
63 /// ```
64 /// use commonlibsse_ng::re::hkArray::hkArray;
65 ///
66 /// let array = hkArray::<u32>::new();
67 /// assert_eq!(array.len(), 0);
68 /// ```
69 #[inline]
70 pub const fn len(&self) -> usize {
71 self.__base.len()
72 }
73
74 /// Returns the capacity of the array.
75 ///
76 /// # Example
77 /// ```
78 /// use commonlibsse_ng::re::hkArray::hkArray;
79 ///
80 /// let array = hkArray::<u32>::new();
81 /// assert_eq!(array.capacity(), 0);
82 /// ```
83 #[inline]
84 pub const fn capacity(&self) -> i32 {
85 self.__base.capacity()
86 }
87
88 /// Checks if the array is empty.
89 ///
90 /// # Example
91 /// ```
92 /// use commonlibsse_ng::re::hkArray::hkArray;
93 ///
94 /// let array = hkArray::<u32>::new();
95 /// assert!(array.is_empty());
96 /// ```
97 #[inline]
98 pub const fn is_empty(&self) -> bool {
99 self.__base.is_empty()
100 }
101
102 /// Reserves capacity for at least `new_capacity` elements.
103 ///
104 /// # Panics
105 /// Panics if `new_capacity` exceeds the internal capacity limit.
106 ///
107 /// # Example
108 /// ```
109 /// use commonlibsse_ng::re::hkArray::hkArray;
110 ///
111 /// let mut array = hkArray::<u32>::new();
112 /// array.reserve(10);
113 /// assert!(array.capacity() >= 10);
114 /// ```
115 #[inline]
116 pub fn reserve(&mut self, new_capacity: i32) {
117 self.__base.reserve(new_capacity);
118 }
119
120 /// Pushes a new element to the end of the array.
121 ///
122 /// # Panics
123 /// Panics if memory allocation fails.
124 ///
125 /// # Example
126 /// ```
127 /// use commonlibsse_ng::re::hkArray::hkArray;
128 ///
129 /// let mut array = hkArray::<u32>::new();
130 /// array.push(42);
131 /// ```
132 #[inline]
133 pub fn push(&mut self, value: T) {
134 self.__base.push(value);
135 }
136
137 /// Removes the last element from the array and returns it, or `None` if it's empty.
138 ///
139 /// # Example
140 /// ```
141 /// use commonlibsse_ng::re::hkArray::hkArray;
142 ///
143 /// let mut array = hkArray::<i32>::new();
144 /// array.push(1);
145 /// assert_eq!(array.pop(), Some(1));
146 /// assert_eq!(array.pop(), None);
147 /// ```
148 #[inline]
149 pub const fn pop(&mut self) -> Option<T> {
150 self.__base.pop()
151 }
152
153 /// Returns a reference to the element at the given index, if it exists.
154 ///
155 /// # Example
156 /// ```
157 /// use commonlibsse_ng::re::hkArray::hkArray;
158 ///
159 /// let mut array = hkArray::<i32>::new();
160 /// array.push(42);
161 /// assert_eq!(array.get(0), Some(&42));
162 /// assert_eq!(array.get(1), None);
163 /// ```
164 #[inline]
165 pub const fn get(&self, index: usize) -> Option<&T> {
166 self.__base.get(index)
167 }
168
169 /// Returns a mutable reference to the element at the given index, if it exists.
170 ///
171 /// # Example
172 /// ```
173 /// use commonlibsse_ng::re::hkArray::hkArray;
174 ///
175 /// let mut array = hkArray::<i32>::new();
176 /// array.push(10);
177 /// if let Some(x) = array.get_mut(0) {
178 /// *x += 1;
179 /// }
180 /// assert_eq!(array[0], 11);
181 /// ```
182 #[inline]
183 pub const fn get_mut(&mut self, index: usize) -> Option<&mut T> {
184 self.__base.get_mut(index)
185 }
186
187 /// Clears the array, removing all elements but preserving the capacity.
188 ///
189 /// # Examples
190 /// ```
191 /// use commonlibsse_ng::re::BSTArray::{BSTArray};
192 ///
193 /// let mut array = BSTArray::<i32>::with_capacity(10);
194 /// array.push(1);
195 /// array.push(2);
196 /// assert_eq!(array.len(), 2);
197 /// array.clear();
198 /// assert_eq!(array.len(), 0);
199 /// assert_eq!(array.capacity(), 10); // Capacity is preserved
200 /// ```
201 #[inline]
202 pub fn clear(&mut self) {
203 self.__base.clear();
204 }
205
206 /// Checks if the array contains the given element.
207 ///
208 /// Returns `true` if the element is present in the array, and `false` otherwise.
209 ///
210 /// # Examples
211 ///
212 /// ```
213 /// use commonlibsse_ng::re::hkArray::hkArray;
214 ///
215 /// let mut array = hkArray::<i32>::with_capacity(10);
216 /// array.push(1);
217 /// array.push(2);
218 /// assert!(array.contains(&1));
219 /// assert!(!array.contains(&3));
220 /// ```
221 #[inline]
222 pub fn contains(&self, value: &T) -> bool
223 where
224 T: PartialEq,
225 {
226 for i in 0..self.len() {
227 if let Some(item) = self.get(i) {
228 if item == value {
229 return true;
230 }
231 }
232 }
233 false
234 }
235
236 /// Retains only the elements that satisfy the predicate.
237 ///
238 /// This method takes a closure that accepts an element of the array and returns a boolean.
239 /// Elements for which the closure returns `true` will be kept, while elements for which
240 /// it returns `false` will be removed.
241 ///
242 /// # Examples
243 ///
244 /// ```
245 /// use commonlibsse_ng::re::hkArray::hkArray;
246 ///
247 /// let mut array = hkArray::<i32>::with_capacity(10);
248 /// array.push(1);
249 /// array.push(2);
250 /// array.push(3);
251 /// array.retain(|&x| x > 1);
252 /// assert_eq!(array.len(), 2);
253 /// assert!(array.contains(&2));
254 /// assert!(array.contains(&3));
255 /// ```
256 #[inline]
257 pub fn retain<F>(&mut self, f: F)
258 where
259 F: FnMut(&T) -> bool,
260 {
261 self.__base.retain(f);
262 }
263
264 /// Removes a range of elements from the array, returning them as a vector.
265 ///
266 /// This method removes the elements within the specified range and returns them as
267 /// a `Vec<T>`. The range must be within the bounds of the array.
268 ///
269 /// # Examples
270 ///
271 /// ```
272 /// use commonlibsse_ng::re::hkArray::hkArray;
273 ///
274 /// let mut array = hkArray::<i32>::with_capacity(10);
275 /// array.push(1);
276 /// array.push(2);
277 /// array.push(3);
278 /// array.push(4);
279 /// array.push(5);
280 /// let drained = array.drain(0..2);
281 /// assert_eq!(drained.collect::<Vec<_>>(), vec![1, 2]);
282 /// assert_eq!(array.len(), 3);
283 /// assert_eq!(array[0], 3);
284 /// assert_eq!(array[1], 4);
285 /// assert_eq!(array[2], 5);
286 /// ```
287 ///
288 /// # Panics
289 /// Panics if the range is out of bounds.
290 #[inline]
291 pub fn drain<R>(&mut self, range: R) -> hkArrayDrain<'_, T, A>
292 where
293 R: core::ops::RangeBounds<usize>,
294 {
295 self.__base.drain(range)
296 }
297
298 /// Return iterator
299 #[inline]
300 pub const fn iter(&self) -> hkArrayRefIterator<'_, T, A> {
301 self.__base.iter()
302 }
303
304 /// Return readonly slice.
305 #[inline]
306 pub const fn as_slice(&self) -> &[T] {
307 self.__base.as_slice()
308 }
309
310 /// Return mutable slice.
311 #[inline]
312 pub const fn as_mut_slice(&mut self) -> &mut [T] {
313 self.__base.as_mut_slice()
314 }
315}
316
317impl<T, A> hkArray<T, A>
318where
319 T: Clone,
320 A: SelflessAllocator,
321{
322 /// Resizes the array to the specified length, filling new elements with the given value.
323 ///
324 /// # Panics
325 /// Panics if `count` is negative or exceeds the maximum allowed capacity.
326 ///
327 /// # Example
328 /// ```
329 /// use commonlibsse_ng::re::hkArray::hkArray;
330 ///
331 /// let mut array = hkArray::<u32>::new();
332 /// array.resize(3, 7);
333 /// assert_eq!(array.len(), 3);
334 /// assert_eq!(array[0], 7);
335 /// ```
336 #[inline]
337 pub fn resize(&mut self, count: i32, value: T) {
338 self.__base.resize(count, value);
339 }
340}
341
342impl<T, A> Default for hkArray<T, A>
343where
344 A: SelflessAllocator,
345{
346 #[inline]
347 fn default() -> Self {
348 Self::new()
349 }
350}
351
352impl<T, A> IntoIterator for hkArray<T, A>
353where
354 A: SelflessAllocator,
355{
356 type Item = T;
357 type IntoIter = hkArrayIterator<T, A>;
358
359 #[inline]
360 fn into_iter(self) -> Self::IntoIter {
361 self.__base.into_iter()
362 }
363}
364
365impl<T, A> Index<usize> for hkArray<T, A>
366where
367 A: SelflessAllocator,
368{
369 type Output = T;
370
371 #[inline]
372 fn index(&self, index: usize) -> &Self::Output {
373 &self.__base[index]
374 }
375}
376
377impl<T, A> IndexMut<usize> for hkArray<T, A>
378where
379 A: SelflessAllocator,
380{
381 #[inline]
382 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
383 &mut self.__base[index]
384 }
385}
386
387#[cfg(test)]
388mod tests {
389 use stdx::alloc::Global;
390
391 use super::{hkArray as hkArray_, *};
392
393 type hkArray<T> = hkArray_<T, Global>;
394
395 #[test]
396 fn test_hk_array_new() {
397 let array: hkArray<i32> = hkArray::new();
398 assert_eq!(array.len(), 0);
399 assert!(array.is_empty());
400 }
401
402 #[test]
403 fn test_hk_array_push_back() {
404 let mut array = hkArray::new();
405 array.push(10);
406 array.push(20);
407
408 assert_eq!(array.len(), 2);
409 assert!(!array.is_empty());
410 assert_eq!(array.index(0), &10);
411 assert_eq!(array.index(1), &20);
412 }
413
414 #[test]
415 fn test_hk_array_resize_smaller() {
416 let mut array = hkArray::new();
417 array.push(10);
418 array.push(20);
419 array.push(30);
420
421 array.resize(2, 0);
422 assert_eq!(array.len(), 2);
423 assert_eq!(array.index(0), &10);
424 assert_eq!(array.index(1), &20);
425 }
426
427 #[test]
428 fn test_hk_array_resize_larger() {
429 let mut array = hkArray::new();
430 array.push(10);
431 array.push(20);
432
433 array.resize(5, 0);
434 assert_eq!(array.len(), 5);
435 assert_eq!(array.index(0), &10);
436 assert_eq!(array.index(1), &20);
437 }
438
439 #[test]
440 fn test_hk_array_into_iterator() {
441 let mut array = hkArray::new();
442 array.push(10);
443 array.push(20);
444
445 let mut iter = array.into_iter();
446 assert_eq!(iter.next(), Some(10));
447 assert_eq!(iter.next(), Some(20));
448 assert_eq!(iter.next(), None); // No more elements
449 }
450
451 #[test]
452 fn test_hk_array_reserve() {
453 let mut array = hkArray::new();
454 array.push(10);
455 array.push(20);
456
457 // Reserve more capacity
458 let initial_capacity = array.capacity();
459 array.reserve(10);
460 assert!(array.capacity() >= initial_capacity);
461 }
462
463 #[test]
464 fn test_hk_array_capacity() {
465 let mut array = hkArray::new();
466 assert_eq!(array.capacity(), 0); // Initially, capacity should be 0 or some small value
467
468 array.push(10);
469 assert!(array.capacity() > 0);
470 }
471}